home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 January / enter-2004-01.iso / files / maxima-5.9.0.exe / {app} / share / maxima / 5.9.0 / src / set.lisp < prev    next >
Encoding:
Text File  |  2003-02-09  |  8.9 KB  |  270 lines

  1. ;; Support for Maxima sets.
  2. ;; Author: Barton Willis
  3. ;; Send bug reports to willisb@unk.edu
  4.  
  5. ;; This code is in the public domain.  It has no warranty. Use this
  6. ;; code at your own risk. 
  7.  
  8. (in-package "MAXIMA")
  9.  
  10. ;; Use the predicate canonlt to order the elements of a set.  The
  11. ;; default is $unorderedp.  The predicate $unorderedp always 
  12. ;; returns true; when canonlt is its default value, sets are 
  13. ;; never sorted. Other choices for $canonlt include $ordergreatp 
  14. ;; and $orderlessp.
  15.  
  16. (defun $unorderedp (a b) t)
  17. (defmvar $canonlt '$unorderedp)
  18.  
  19. ;; The set package doesn't distinguish between sets and lists.  We're
  20. ;; in trouble if we need to work simultaneously with a set of 
  21. ;; lists and a set of sets.  The commerical Macsyma seems to treat
  22. ;; all set elements as lists; thus setify([[1,2],[2,1]) returns 
  23. ;; [[1,2],[2,1]] because [1,2] and [2,1] are treated as lists 
  24. ;; (and consequently they are not equal).  In this package, the 
  25. ;; user may decide if set elements that are lists are treated as 
  26. ;; lists or as sets.  When $set_elements_can_be_sets is true 
  27. ;; (the default),  set elements that are lists are treated 
  28. ;; as sets; otherwise,  when  $set_elements_can_be_sets is 
  29. ;; false, set elements that are lists are treated as lists.
  30.  
  31. (defmvar $set_elements_can_be_sets t)
  32.  
  33. ;; For non-lists x and y, equalp(x,y) returns is(ratsimp(x-y)=0).
  34. ;; Signal an error if either x or y is a list. Since equalp uses 
  35. ;; ratsimp, equalp(x/x,1) is true and equalp(x^(a*b),(x^a)^b)
  36. ;; is false. 
  37.  
  38. (defun $equalp (x y)
  39.   (cond ((or ($listp x) ($listp y))
  40.      (merror "Both arguments to EQUALP must be non-lists."))    
  41.      (t ($xequalp x y))))
  42.  
  43. ;; If you are certain that x and y are not lists, you might call
  44. ;; (at Maxima level) ?xequalp instead of equalp.
  45.  
  46. (defun $xequalp (x y)
  47.   (like 0 ($ratsimp (add* x (*mminus y)))))
  48.  
  49. ;; If x and y are not lists, $elem_equalp(x,y) returns 
  50. ;; equalp(x,y).  If x and y are both lists, return 
  51. ;; setequality(x,y) if set_elements_can_be_sets; otherwise 
  52. ;; return equalp(x[1],y[1]) and equalp(x[2],y[2]) and ....
  53. ;; Finally, if exactly one of x or y is a list, return false. 
  54.  
  55. (defun $elem_equalp (x  y)
  56.   (cond ((and ($listp x) ($listp y)) 
  57.      (cond ($set_elements_can_be_sets
  58.         ($setequality x y))
  59.            ((and ($emptyp x) ($emptyp y)) t)
  60.            (t
  61.         (and 
  62.          (= ($length x) ($length y))
  63.          ($elem_equalp ($first x) ($first y))
  64.          ($elem_equalp ($rest x) ($rest y))))))
  65.     ((or ($listp x) ($listp y)) nil)
  66.     (t ($xequalp x y))))
  67.  
  68. ;;  Adjoin x to the Maxima list a; use equalp for the equality test.
  69. ;;  When a isn't a list, signal an error.
  70.  
  71. (defun $adjoin (x a)
  72.   (cond (($listp a)
  73.      (cons '(mlist) (adjoin x (margs a) :test #'$elem_equalp)))
  74.     (t (merror "The second argument to ADJOIN must be a list"))))
  75.  
  76. ;; Setify removes duplicates from a Maxima list and sorts the
  77. ;; list using the partial ordering function canonlt. To remove the
  78. ;; duplicates from the list, we use element_equalp to test for equality.
  79. ;; When the argument isn't a list, signal an error.
  80.  
  81. (defun $setify (a)
  82.   (cond (($listp a)
  83.      (mysort (cons '(mlist) (remove-duplicates (margs a) :test #'$elem_equalp))))
  84.     (t (merror "The argument to SETIFY must be a list."))))
  85.  
  86. ;; When $canonlt is $unorderedp, don't sort; when $canonlt isn't
  87. ;; $unorderedp, sort the list using the predicate $canonlt.
  88.  
  89. (defun mysort (a)
  90.   (cond ((eq $canonlt '$unorderedp) a)
  91.     (t ($sort a $canonlt))))
  92.  
  93. ;; The maxima function call union(a1,a2,...an) forms the union of the
  94. ;; sets a1,a2,...an.
  95.  
  96. (defmfun $union ( &rest a)
  97.   (setq a (margs a))
  98.   (cond ((member nil (mapcar #'$listp a))
  99.      (merror "Each argument to UNION must be a list."))
  100.     (t
  101.      (cons '(mlist) (remove-duplicates (apply 'append  (map 'list 'rest a)) :test #'$elem_equalp)))))
  102.  
  103. ;; Remove elements of b from a.  Signal an error if a or b aren't lists.
  104. ;; Use element_equalp for the equality test.
  105.  
  106. (defun $setdifference (a b)
  107.   (cond ((and ($listp a) ($listp b))
  108.      (cons '(mlist) (set-difference (margs a) (margs b) :test #'$elem_equalp)))
  109.     (t (merror "Both arguments to SETDIFFERENCE must be lists."))))
  110.  
  111. ;; Return the intersection of lists a and b.  Use element_equalp for the
  112. ;; equality test. Signal an error if a or b aren't lists.
  113.  
  114. (defmfun $intersection ( &rest a)
  115.   (setq a (margs a))
  116.   (cond ((member nil (mapcar #'$listp a))
  117.      (merror "Each argument to INTERSECTION must be a list."))
  118.     (t
  119.      (setq a (mapcar #'margs a))
  120.      (cons '(mlist)
  121.            (reduce #'(lambda (x y)
  122.                (intersection x y :test #'$elem_equalp))
  123.                a :from-end nil)))))
  124.  
  125. ;; Return true iff a is a subset of b.  Signal an error if
  126. ;; a or b aren't Maxima lists.
  127.  
  128. (defun $subsetp (a b)
  129.   (cond ((and ($listp a) ($listp b))
  130.      (xsubsetp (margs a) b))
  131.     (t (merror "Both arguments to SUBSETP must be lists."))))
  132.  
  133. ;; xsubsetp returns true if and only if each element of the Lisp
  134. ;; list a is a member of the Maxima list b.  This function isn't 
  135. ;; inteneded to be a user function; it doesn't check whether b is a 
  136. ;; Maxima list. Notice that the empty set is a subset of every 
  137. ;; set.
  138.  
  139. (defun xsubsetp (a b)
  140.   (cond ((null a) t)
  141.     (t
  142.      (and ($elementp (car a) b) (xsubsetp (cdr a) b)))))
  143.  
  144. ;; Return true iff a is a subset of b and b is a subset of a; return
  145. ;; false if a or b are not lists.
  146.  
  147. (defun $setequality (a b)
  148.   (cond ((and ($listp a) ($listp b))
  149.      (if (and ($subsetp a b) ($subsetp b a)) t nil))
  150.     (t nil)))
  151.  
  152.  
  153. ;; Return true iff x as an element of the list a; use $elem_equalp 
  154. ;; to test for equality if x isn't a list and use $setequality to 
  155. ;; test for equality if x is a list.  Return false if a isn't a list.
  156.  
  157. (defun $elementp (x a)
  158.   (cond (($listp a)
  159.      (cond (($listp x)
  160.         (cond ($set_elements_can_be_sets
  161.                (if (member x (margs a) :test #'$setequality) t nil))
  162.               (t
  163.                (if (member x (margs a) :test #'$elem_equalp) t nil))))
  164.            (t
  165.         (if (member x (margs a) :test #'$elem_equalp) t nil))))
  166.     (t nil)))
  167.  
  168. ;; Return true if e is an empty Maxima list; otherwise, signal an
  169. ;; error.
  170.  
  171. (defun $emptyp(e)
  172.   (cond (($listp e)
  173.      (like e '((mlist))))
  174.     (t (merror "Argument to EMPTYP must be a list."))))
  175.  
  176. ;; Return an n element Maxima list [e,e,e,...e]. When n < 0 or
  177. ;; n isn't an integer, signal an error.
  178.  
  179. (defun $dupe (e n)
  180.   (cond ((and (integerp n) (> n -1))
  181.      (cons '(mlist) (make-list n :initial-element e)))
  182.     (t (merror "Second argument to DUPE must be a nonnegative integer."))))
  183.  
  184. ;; Return true if and only if the lists a and b are disjoint;
  185. ;; signal an error if a or b aren't lists.
  186.  
  187. (defun $disjointp (a b)
  188.   (cond ((and ($listp a) ($listp b))
  189.      (not (intersection (margs a) (margs b) :test #'$elem_equalp)))
  190.     (t (merror "Both arguments to DISJOINTP must be lists."))))
  191.  
  192. ;; Return those elements of a for which the predicate f evaluates
  193. ;; to true; signal an error if a isn't a list.
  194.  
  195. (defun $subset (a f)
  196.   (cond (($listp a)
  197.      (setq a (margs a))
  198.      (let ((acc nil))
  199.        (dolist (x a (cons '(mlist) acc))
  200.               (if (mfuncall f x) (setq acc (cons x acc))))))
  201.     (t (merror "First argument to SUBSET must be a list."))))
  202.  
  203. ;; Return the union of a - b and b - a; signal an error if a or b
  204. ;; aren't lists.
  205.  
  206. (defun $symmdifference (a b)
  207.   (cond ((and ($listp a) ($listp b))
  208.      (mfuncall '$union ($setdifference a b) ($setdifference b a)))
  209.     (t (merror "Both arguments to SYMMDIFFERENCE must be lists."))))
  210.  
  211. ;; Return a list of the elements in b that are not in a.
  212.  
  213. (defun $complement (a b)
  214.   (cond ((and ($listp a) ($listp b))
  215.      ($setdifference b a))
  216.      (t (merror "Both arguments to COMPLEMENT must be lists."))))
  217.  
  218. ;; Return true if and only if the argument is a Maxima list and the
  219. ;; list does not have duplicate elements.  setp doesn't check that
  220. ;; the list is ordered according to canonlt.
  221.  
  222. (defun $setp (a)
  223.   (and ($listp a) (setp (margs a))))
  224.  
  225. (defun setp (a)
  226.   (cond ((null a) t)
  227.     (t (and (setp (cdr a)) (not (member (car a) (cdr a) :test #'$elem_equalp))))))
  228.  
  229. ;; Return the set of all subsets of a.  If a has n elements, powerset(a) has
  230. ;; 2^n elements.  Signal an error if the argument isn't a Maxima list.
  231.  
  232. (defun $powerset (a)
  233.   (cond (($listp a)
  234.      (setq a ($setify a))
  235.      (cons '(mlist) (mapcar #'(lambda (x) (cons '(mlist) x))
  236.                 (powerset (margs a)))))
  237.     (t (merror "Argument to POWERSET must be a list."))))
  238.  
  239. (defun powerset (a)
  240.   (cond ((null a) (list nil))
  241.     (t
  242.      (let ((x (car a))
  243.            (b (powerset (cdr a))))
  244.        (append b (mapcar #'(lambda (u) (cons x u)) b))))))
  245.  
  246. ;; Return the set of all subsets of a that have exactly n elements.
  247. ;; Signal an error if the first argument isn't a Maxima list or if
  248. ;; the second argument isn't a nonnegative integer.
  249.  
  250. (defun $subpowerset (a n)
  251.   (cond (($listp a)
  252.      (setq a ($setify a))
  253.      (cond ((and (integerp n) (> n -1))
  254.         (cons '(mlist) (mapcar #'(lambda (x) (cons '(mlist) x))
  255.                        (subpowerset (margs a) n))))
  256.            (t
  257.         (merror "Second argument to SUBPOWERSET must
  258. be a nonnegative integer."))))
  259.     (t (merror "First argument to SUBPOWERSET must be a list."))))
  260.  
  261. (defun subpowerset (a n)
  262.   (cond ((or (< n 1) (null a))
  263.      nil)
  264.     ((= n 1) (mapcar #'list a))
  265.     (t (let ((x (car a))
  266.          (b (subpowerset (cdr a) (- n 1))))
  267.          (append (subpowerset (cdr a) n)
  268.              (mapcar #'(lambda (u) (cons x u)) b))))))
  269.  
  270.